package cn.boodqian.airdata;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.TimeZone;
import java.util.logging.Logger;

import javax.servlet.http.*;
import org.apache.commons.lang3.time.DateUtils;

@SuppressWarnings("serial")
public class BuildHistoryServlet extends HttpServlet {
	private final static Logger Log = Logger.getLogger(BuildHistoryServlet.class .getName());
	private Calendar now = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws IOException {
		resp.setContentType("text/plain");
		resp.setCharacterEncoding("UTF-8");

		ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String,String>>();
		list.addAll(BeijingAirDataProvider.locationList);
		list.addAll(ShanghaiAirDataProvider.locationList);
		list.addAll(ShanghaiUSAirDataProvider.locationList);
		
		ArrayList<HashMap<String, String>> cnemc_list = CNEMCAirDataProvider.getLocationList("zh");
		if( cnemc_list != null ) list.addAll(cnemc_list);
		
//		if( now.get(Calendar.HOUR_OF_DAY) != 1 ) {
//			String msg = String.format("Not good time for history building: ", Global.FmtUTC8.format(now.getTime()));
//			Log.info( msg );
//			resp.getWriter().println(msg);
//			return;
//		}
		for( HashMap<String, String> location : list ) {
			String id = location.get("id");

			if( AirdataServlet.locationMappingMap.containsKey(id) )
				id = AirdataServlet.locationMappingMap.get(id);
		
			buildDailyHistory(id);
			
			buildMonthlyHistory(id);
		}
		
		resp.getWriter().println("BuildHistory Done");
	}
	
	// Build 30-day history for location id
	private void buildDailyHistory( String id )
	{
		Log.info(id + " - Building Daily history");
		
		// From which field we calculate the average
		int baseField = Calendar.HOUR_OF_DAY;
		AirData airdata = AirdataCache.getAirdataFromCache(id, baseField, AirdataCache.fieldDuration(baseField));
		if( airdata == null || airdata.getTime() == null ) {
			Log.info("no data");
			return;
		}

		Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
		cal.setTime( airdata.getTime() );
		Log.info( String.format("Cached: %s, Now: %s", Global.FmtUTC8.format(cal.getTime()), Global.FmtUTC8.format(now.getTime())) );
		
		// 00:00 AM of yesterday
		Calendar yesterday = (Calendar) now.clone();
		yesterday.add(Calendar.DAY_OF_MONTH, -1);
		yesterday = DateUtils.truncate(yesterday, Calendar.DAY_OF_MONTH);
		
		HashMap<String, Object> datamap = new HashMap<String, Object>();
		for( String type : Global.AirType ) {
			List<Float> list = airdata.getData(type);
			if( list == null ) continue;
			
			int count = 0;
			Float sum = 0f;
			Calendar caltmp = (Calendar) cal.clone();
			for( int i = list.size() - 1; i >= 0; i-- ) {
				String logmsg = String.format(" Data at %s - ", Global.FmtUTC8.format(caltmp.getTime()));
				caltmp.add(Calendar.HOUR_OF_DAY, -1);
				if ( DateUtils.isSameDay(caltmp, yesterday) ) {
					Float value = list.get(i);
					if( value > 0f ) {
						sum += list.get(i);
						count ++;
					}
					logmsg += value;
				} else {
					logmsg += "skipped";
				}
				Log.finer(type + logmsg);
			}
			Float average = 0f;
			if( count > 0 ) average = sum/count;
			datamap.put(type, average);
		}
		
		String []a = id.split("/");
		AirdataCache.updateAirdataCache(a[0], a[1], Calendar.DAY_OF_MONTH, datamap, yesterday.getTime());
	}
	
	// Build 12-month history for location id
	private void buildMonthlyHistory( String id )
	{
		if( now.get(Calendar.DAY_OF_MONTH) != 1 ) {
			return;
		}
		
		Log.info(id + " - Building monthly history");
		
		// Calculate month average for last month
		int baseField = Calendar.DAY_OF_MONTH;
		AirData airdata = AirdataCache.getAirdataFromCache(id, baseField, AirdataCache.fieldDuration(baseField));
		if( airdata == null || airdata.getTime() == null ) {
			Log.info("no data");
			return;
		}

		Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
		cal.setTime( airdata.getTime() );
		Log.info( String.format("Cached: %s, Now: %s", Global.FmtUTC8.format(cal.getTime()), Global.FmtUTC8.format(now.getTime())) );
		
		// get the first day of last month
		Calendar lastmonth = (Calendar) now.clone();
		lastmonth.add(Calendar.MONTH, -1);
		lastmonth = DateUtils.truncate(lastmonth, Calendar.MONTH);
		
		HashMap<String, Object> datamap = new HashMap<String, Object>();
		for( String type : Global.AirType ) {
			List<Float> list = airdata.getData(type);
			if( list == null ) continue;
			
			int count = 0;
			Float sum = 0f;
			Calendar caltmp = (Calendar) cal.clone();
			for( int i = list.size() - 1; i >= 0; i-- ) {
				String logmsg = String.format(" Data at %s - ", Global.FmtUTC8.format(caltmp.getTime()));
				caltmp.add(Calendar.DAY_OF_MONTH, -1);
				if ( DateUtils.isSameDay (
						DateUtils.truncate(caltmp, Calendar.MONTH),
						lastmonth) ) {
					Float value = list.get(i);
					if( value > 0f ) {
						sum += list.get(i);
						count ++;
					}
					logmsg += value;
				} else {
					logmsg += "skipped";
				}
				Log.finer(type + logmsg);
			}
			Float average = 0f;
			if( count > 0 ) average = sum/count;
			datamap.put(type, average);
		}
		
		String []a = id.split("/");
		AirdataCache.updateAirdataCache(a[0], a[1], Calendar.MONTH, datamap, lastmonth.getTime());
	}
}
